package com.smartinput.voice.application.service

import com.smartinput.voice.config.AudioConfig
import org.springframework.stereotype.Service
import java.io.File
import java.io.FileOutputStream
import java.nio.file.Files
import java.util.concurrent.TimeUnit
import org.slf4j.LoggerFactory

@Service
class WhisperSpeechRecognitionService(
    private val audioConfig: AudioConfig
) : SpeechRecognitionManager.SpeechRecognitionService {
    
    private val logger = LoggerFactory.getLogger(WhisperSpeechRecognitionService::class.java)
    
    // Whisper模型路径配置
    private val whisperModelPath = System.getProperty("whisper.model.path", "/opt/whisper/models/ggml-base.bin")
    private val whisperExecutable = System.getProperty("whisper.executable", "/opt/whisper/whisper")
    
    private fun runWhisperRecognition(audioFilePath: String): String {
        val audioFile = File(audioFilePath)
        val outputDir = audioFile.parentFile
        val baseName = audioFile.nameWithoutExtension
        val outputFilePath = File(outputDir, "${baseName}").absolutePath
        
        logger.info("Whisper识别开始: audioFile=${audioFile.absolutePath}, outputFile=${outputFilePath}")
        
        val processBuilder = ProcessBuilder(
            whisperExecutable,
            "-m", whisperModelPath,
            "-f", audioFilePath,
            "-l", "zh", // 指定中文语言
            "--output-txt", // 输出文本格式
            "--output-file", "${outputFilePath}" // 指定输出文件路径，包含.txt扩展名
        )
        
        processBuilder.redirectErrorStream(true)
        val process = processBuilder.start()
        
        // 读取进程输出
        val output = process.inputStream.bufferedReader().readText()
        logger.info("Whisper进程输出: $output")
        
        // 等待进程完成，最多等待30秒
        val completed = process.waitFor(30, TimeUnit.SECONDS)
        
        if (!completed) {
            process.destroyForcibly()
            throw RuntimeException("Whisper识别超时")
        }
        
        val exitCode = process.exitValue()
        logger.info("Whisper进程退出码: $exitCode")
        
        if (exitCode != 0) {
            throw RuntimeException("Whisper识别失败，退出码: $exitCode")
        }
        
        // 读取输出文件
        val outputFile = File("${outputFilePath}.txt")
        
        return if (outputFile.exists()) {
            val text = outputFile.readText().trim()
            logger.info("Whisper识别成功，文本长度: ${text.length}")
            // 清理输出文件
            outputFile.delete()
            text
        } else {
            // 检查目录中的所有文件
            val allFiles = outputDir.listFiles()?.map { it.name } ?: emptyList()
            logger.error("Whisper输出文件不存在: ${outputFile.absolutePath}")
            logger.error("目录中的所有文件: $allFiles")
            throw RuntimeException("Whisper输出文件不存在")
        }
    }
    
    fun isWhisperAvailable(): Boolean {
        return try {
            val processBuilder = ProcessBuilder(whisperExecutable, "--help")
            val process = processBuilder.start()
            val completed = process.waitFor(5, TimeUnit.SECONDS)
            completed && process.exitValue() == 0
        } catch (e: Exception) {
            logger.warn("Whisper不可用: ${e.message}")
            false
        }
    }
    
    override val serviceName: String = "Whisper"
    
    override fun recognizeAudio(audioData: ByteArray): SpeechRecognitionManager.RecognitionResult {
        return try {
            logger.info("Whisper开始处理音频数据，大小: ${audioData.size} bytes")
            
            // 创建临时WAV文件
            val tempDir = Files.createTempDirectory("whisper_audio")
            val wavFile = File(tempDir.toFile(), "audio_${System.currentTimeMillis()}.wav")
            
            logger.info("创建临时WAV文件: ${wavFile.absolutePath}")
            
            // 写入WAV音频数据
            FileOutputStream(wavFile).use { fos ->
                fos.write(audioData)
            }
            
            // 检查文件是否存在和大小
            if (!wavFile.exists()) {
                throw RuntimeException("临时WAV文件创建失败")
            }
            
            logger.info("WAV文件创建成功: ${wavFile.absolutePath}, 文件大小: ${wavFile.length()} bytes")
            
            // 调用Whisper进行识别
            val recognizedText = runWhisperRecognition(wavFile.absolutePath)
            
            // 清理临时文件
            wavFile.delete()
            tempDir.toFile().deleteRecursively()
            
            SpeechRecognitionManager.RecognitionResult(
                text = recognizedText,
                confidence = 0.9, // Whisper不直接提供置信度，使用默认值
                success = true
            )
            
        } catch (e: Exception) {
            logger.error("Whisper语音识别失败", e)
            SpeechRecognitionManager.RecognitionResult(
                text = "",
                confidence = 0.0,
                success = false,
                error = e.message
            )
        }
    }
    
    override fun isAvailable(): Boolean {
        return isWhisperAvailable()
    }
    
    data class RecognitionResult(
        val text: String,
        val confidence: Double,
        val success: Boolean,
        val error: String? = null
    )
} 